package
{
	// + ----------------------------------------
	//		[ IMPORTS ]
	// + ----------------------------------------
	
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.AsyncErrorEvent;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.StatusEvent;
	import flash.net.LocalConnection;
	import flash.text.TextField;
	import flash.text.TextFormat;
	
	import net.jansensan.as3maxlikeui.MessageBox;
	import net.jansensan.as3maxlikeui.OutputBox;
	
	
	/**
	 * @author Mat Janson Blanchet
	 */
	[SWF(frameRate="30", backgroundColor="#ffffff", width="520", height="600")]
	/**
	 * 
	 * @author user
	 */
	public class CommunicationWithFacebook extends Sprite
	{
		// + ----------------------------------------
		//		[ CONSTANTS ]
		// + ----------------------------------------
		
		// private
		private	const	WIDTH				:uint = 520;
		private	const	HEIGHT				:uint = 600;
		private	const	CALL_FBJS			:String = "callFBJS";
		
		
		// + ----------------------------------------
		//		[ VARIABLES ]
		// + ----------------------------------------
		
		// display objects
		private	var	_output					:OutputBox;
		private	var	_goToURLButton			:MessageBox;
		private	var	_callFBJSButton			:MessageBox;
		
		// private / protected
		private	var	_HTMLVars				:Object;
		
		private	var	_outgoingConnection		:LocalConnection;
		private	var	_outgoingConnectionName	:String;
		
		private	var	_incomingConnection		:LocalConnection;
		private	var	_incomingConnectionName	:String;
		
		
		// + ----------------------------------------
		//		[CONSTRUCTOR ]
		// + ----------------------------------------
		
		public function CommunicationWithFacebook()
		{
			// set some basic stage params
			initStage();
			
			// wait for the html vars to be loaded
			loaderInfo.addEventListener(Event.COMPLETE, loaderInfoCompleteHandler, false, 0, true);
		}
		
		
		// + ----------------------------------------
		//		[ PUBLIC METHODS ]
		// + ----------------------------------------
		
		/**
		 * Displays the message sent by Facebook in the output box.
		 * 
		 * @param	title	Title of the message
		 * @param	message	Content of the message
		 */
		public function as3FunctionForFBJS(title:String, message:String):void
		{
			_output.text = "<b>" + title + "</b><br/>" + message;
		}
		
		
		// + ----------------------------------------
		//		[ PRIVATE/PROTECTED METHODS ]
		// + ----------------------------------------
		
		private function initStage():void
		{
			// set some initial values for the stage
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
		}
		
		
		private function init():void
		{
			addOutputField();
			outputHTMLVars();
			
			addGoToURLButton();
			addCallFBJSBridgeButton();
			
			initFBJSBridge();
		}
		
		
		private function addOutputField():void
		{
			_output = new OutputBox();
			_output.init();
			_output.resize(WIDTH, HEIGHT * 0.75);
			_output.y = 0;
			addChild(_output);
		}
		
		
		private function addGoToURLButton():void
		{
			_goToURLButton = new MessageBox("Go to a URL");
			_goToURLButton.buttonMode = true;
			_goToURLButton.addEventListener(MouseEvent.CLICK, goToURLClickHandler, false, 0, true);
			_goToURLButton.init();
			_goToURLButton.x = WIDTH * 0.5 - _goToURLButton.width * 0.5;
			_goToURLButton.y = HEIGHT - 2 * (_goToURLButton.height + 8);
			addChild(_goToURLButton);
		}
		
		
		private function addCallFBJSBridgeButton():void
		{
			_callFBJSButton = new MessageBox("Call Facebook");
			_callFBJSButton.buttonMode = true;
			_callFBJSButton.addEventListener(MouseEvent.CLICK, callFBJSClickHandler, false, 0, true);
			_callFBJSButton.init();
			_callFBJSButton.x = WIDTH * 0.5 - _callFBJSButton.width * 0.5;
			_callFBJSButton.y = HEIGHT - _callFBJSButton.height;
			addChild(_callFBJSButton);
		}
		
		
		private function outputHTMLVars():void
		{
			//traces all the 
			var outputText:String = "<b>values in HTMLVars:</b><br/><br/>";
			
			for(var key:String in _HTMLVars)
			{
				outputText += "<b>" + key + "</b>: " + _HTMLVars[key] + "<br/>";
			}
			
			_output.text = outputText;
		}
		
		
		private function gotoURL():void
		{
			try
			{
				// 2 options are possible to redirect to a URL
				
				// using AS3's navigateToURL, exposed in Facebook's LocalConnection
				_outgoingConnection.send	(	_outgoingConnectionName,
												"navigateToURL",
												"http://jansensan.net"
											); 
				
				// using document.setLocation, available via FBJS
				/*
				_outgoingConnection.send	(	_outgoingConnectionName,
												CALL_FBJS,
												"document.setLocation",
												["http://jansensan.net"]
											);
				*/
			}
			catch(error:Error)
			{
				trace("\n", this, "--- gotoURL ---");
				trace("\t", "error:", error);
			}
		}
		
		
		private function callFBJSBridge():void
		{
			try
			{
				_outgoingConnection.send	(	_outgoingConnectionName,
												CALL_FBJS,
												"fbjsFunctionForAS3",
												[	
													"Message sent from AS3",
													"Hello Facebook!"
												]
											); 
			}
			catch(error:Error)
			{
				trace("\n", this, "--- callFBJSBridge ---");
				trace("\t", "error:", error);
			}
		}
		
		
		private function initFBJSBridge():void
		{
			_outgoingConnectionName = _HTMLVars.fb_local_connection;
			_outgoingConnection = new LocalConnection();
			_outgoingConnection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, connectionSecurityErrorHandler, false, 0, true);
			_outgoingConnection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, connectionASyncErrorHandler, false, 0, true);
			_outgoingConnection.addEventListener(StatusEvent.STATUS, connectionStatusHandler, false, 0, true);
			
			_incomingConnectionName = _HTMLVars.fb_fbjs_connection;
			_incomingConnection = new LocalConnection();
			_incomingConnection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, connectionSecurityErrorHandler, false, 0, true);
			_incomingConnection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, connectionASyncErrorHandler, false, 0, true);
			_incomingConnection.addEventListener(StatusEvent.STATUS, connectionStatusHandler, false, 0, true);
			_incomingConnection.allowDomain("apps.facebook.com", "apps.*.facebook.com");
			_incomingConnection.client = this;
			try
			{
				_incomingConnection.connect(_incomingConnectionName);
			}
			catch(error:Error)
			{
				trace("\n", this, "--- initFBJSBridge ---");
				trace("\t", "error:", error);
			}
		}
		
		
		// + ----------------------------------------
		//		[ EVENT HANDLERS ]
		// + ----------------------------------------
		
		private function loaderInfoCompleteHandler(event:Event):void
		{
			loaderInfo.removeEventListener(Event.COMPLETE, loaderInfoCompleteHandler);
			_HTMLVars = loaderInfo.parameters;
			init();
		}
		
		
		private function connectionSecurityErrorHandler(event:SecurityErrorEvent):void
		{
			trace("\n", this, "--- connectionSecurityErrorHandler ---");
			
			var target:LocalConnection = event.target as LocalConnection;
			switch(target)
			{
				case _incomingConnection:
					trace("\t", "incoming connection error:", event);
					break;
				
				case _outgoingConnection:
					trace("\t", "outgoing connection error:", event);
					break;
				
				default:
					trace("\t", "error:", event);
					break;
			}
		}
		
		
		private function connectionASyncErrorHandler(event:AsyncErrorEvent):void
		{
			trace("\n", this, "--- connectionASyncErrorHandler ---");
			
			var target:LocalConnection = event.target as LocalConnection;
			switch(target)
			{
				case _incomingConnection:
					trace("\t", "incoming connection error:", event.error);
					break;
				
				case _outgoingConnection:
					trace("\t", "outgoing connection error:", event.error);
					break;
				
				default:
					trace("\t", "error:", event.error);
					break;
			}
		}
		
		
		private function connectionStatusHandler(event:StatusEvent):void
		{
			trace("\n", this, "--- connectionStatusHandler ---");
			
			var target:LocalConnection = event.target as LocalConnection;
			switch(target)
			{
				case _incomingConnection:
					trace("\t", "incoming connection error:", event);
					break;
				
				case _outgoingConnection:
					trace("\t", "outgoing connection error:", event);
					break;
				
				default:
					trace("\t", "error:", event);
					break;
			}
		}
		
		
		private function goToURLClickHandler(event:MouseEvent):void
		{
			gotoURL();
		}
		
		
		private function callFBJSClickHandler(event:MouseEvent):void
		{
			callFBJSBridge();
		}
		
		
	}
}